﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data.OleDb;
using System.IO;
using System.Data;
using GestorSQL.BusinessEntities;
using GestorSQL.DAO.FileManager;
using GestorSQL.BLL.ImplementationsBridge;

namespace GestorSQL.BLL.QueryExecutions
{
    public class BLLReader
    {
        #region Variables Privadas
        private IDataReader reader = null;
        private Caso caso = null;
        private IFileManager fileManager = null;
        private bool _omitFirstResult = false;
        private bool _omitLastResult = false;
        private string _lastResultColumnName = null;
        private int _resultCount = 0;
        private int _rowCount = 0;
        private bool _nextResultFail = false;
        private ResulType _resultType = ResulType.None;
        private string _message = string.Empty;
        private StringBuilder _finalMessage = new StringBuilder();
        #endregion

        #region Propiedades

        public int NumberOfColumns { get { return reader.FieldCount; } }
        public int RecordsAffected { get { return reader.RecordsAffected; } }
        public int FieldCount { get { return reader.FieldCount; } }
        public string Message
        {
            get
            {
                if (_resultType == ResulType.Select)
                    _message = string.Format(QueryResult.ROWS_OBTAINED, _rowCount);

                return _message;
            }
            private set { _message = value; }
        }

        public string FinalMessage { get { return _finalMessage.ToString(); } }

        public List<string> Columns
        {
            get
            {
                List<string> _columns = new List<string>();
                foreach (DataRow row in reader.GetSchemaTable().Rows)
                    _columns.Add(row.ItemArray.GetValue(0).ToString());

                return _columns;
            }
        }
        public ResulType ResultType
        {
            get
            {
                if (_omitFirstResult && _resultCount == 0)
                {
                    try
                    {
                        _resultCount++;
                        reader.NextResult();
                    }
                    catch (Exception ex)
                    {
                        _message = ex.Message;
                        _nextResultFail = true;
                    }
                }
                if (_nextResultFail)
                    _resultType = ResulType.Fail;
                else if (reader.RecordsAffected == -1)
                {
                    _message = string.Format(QueryResult.ROWS_OBTAINED, _rowCount);
                    _resultType = ResulType.Select;
                }
                else
                {

                    _message = string.Format(QueryResult.ROWS_AFFECTED, reader.RecordsAffected);
                    _resultType = ResulType.Modification;
                }
                return _resultType;
            }
        }

        #endregion

        #region Metodos publicos
        public BLLReader(IDataReader reader, Caso caso, bool omitFirstResult, bool omitLastResult, string lastResultColumnName)
        {
            fileManager = ImplementationBridge.GetFileManager("Text");
            this.caso = caso;
            this.reader = reader;
            this._omitFirstResult = omitFirstResult;
            this._omitLastResult = omitLastResult;
            this._lastResultColumnName = lastResultColumnName;
        }

        public bool Read()
        {
            bool ret = true;

            if (ret) _rowCount++;

            ret = reader.Read();

            return ret;
        }

        public bool NextResult()
        {
            bool ret = true;
            try
            {
                ret = reader.NextResult();
                if (_omitLastResult)
                    if (Columns.Count > 0 && Columns[0].Equals(_lastResultColumnName))
                        return false;

                _nextResultFail = false;
            }
            catch (Exception ex)
            {
                _nextResultFail = true;
                _message = ex.Message;
                ret = true;
            }
            _finalMessage.Append(_message).AppendLine();
            _rowCount = 0;
            if (ret) _resultCount++;
            return ret;
        }

        public object[] GetRowData()
        {
            StringBuilder sb = new StringBuilder();
            object[] ret = new object[reader.FieldCount];

            for (int i = 0; i < ret.Length; i++)
            {
                ret[i] = reader[i];

                if (IsProduction(this.caso.Historia.Estado_))
                    sb.Append(ret[i]).Append("\t");
            }

            if (IsProduction(this.caso.Historia.Estado_))
                fileManager.SaveAppendFile(PathGetter.GetProdPath(caso, caso.SolucionActual.Value), PathGetter.SALIDA, sb.ToString());


            return ret;
        }

        #endregion

        #region Metodos privados
        private static bool IsProduction(EstadoCaso estado)
        {
            return estado == EstadoCaso.AutorizadoAsistido || estado == EstadoCaso.AutorizadoAutomatico;
        }
        #endregion
    }
}
